<template>
  <div class="app-container">
    <el-form
      :disabled="formConfig.disabled?formConfig.disabled:false"
      :inline="formConfig.inline?formConfig.inline:false"
      :inline-message="formConfig.inlineMessage?formConfig.inlineMessage:false"
      :status-icon="formConfig.statusIcon?formConfig.statusIcon:false"
      :label-position="formConfig.labelPosition?formConfig.labelPosition:'right'"
      :label-width="formConfig.labelWidth?formConfig.labelWidth:'100px'"
      :model="insideData"
      :rules="rules"
      :size="formConfig.size?formConfig.size:'small'"
      class="demo-ruleForm xvc-dialog-form superForm"
      :class="formConfig.className"
      ref="Form"
    >
    <template v-for="(item,idx) in insidFormConfigItems">
      <el-form-item
        :key="idx"
        :label="item.title"
        :prop="item.key"
        v-if="item.show ? item.show() : true"
      >
        <!-- input 默认输入框 -->
        <el-input
          :disabled="item.disabled?item.disabled:false"
          :maxlength="item.maxlength?item.maxlength:10"
          :placeholder="item.placeholder?item.placeholder:'请输入'"
          @input="value=>change(insideData,item.change,idx)"
          @clear="$refs.Form.validateField(item.key)"
          clearable
          v-if="!item.type||item.type ==='input'"
          v-model="insideData[item.key]"
        >
          <template v-if="item.slot" slot="append">{{ item.slot }}</template>
        </el-input>
        <!-- select 下拉框 -->
        <el-select
          :disabled="item.disabled?item.disabled:false"
          @change="value=>change(value,item.change)"
          readonly
          clearable
          placeholder="请选择"
          v-else-if="item.type ==='select'"
          v-model="insideData[item.key]"
        >
          <el-option
            :key="idx"
            :label="group.name"
            :value="group.code"
            v-for="(group,idx) in item.group"
          ></el-option>
        </el-select>

        <el-date-picker
          v-model="insideData[item.key]"
          v-else-if="item.type ==='date'"
          :align="item.align"
          :type="item.pickerType"
          :picker-options="item.pickerOptions"
          :format="item.format"
          :range-separator="item.rangeSeparator || '-'"
          :start-placeholder="item.startPlaceholder || '开始日期'"
          :end-placeholder="item.endPlaceholder || '结束日期'"
          :placeholder="item.placeholder || '请选择'"
          :unlink-panels="item.unlinkPanels"
          :popper-class="item.popperClass"
          :default-value="item.defaultValue"
          :default-time="item.defaultTime"
          :value-format="item.valueFormat || 'timestamp'"
          :readonly="item.readonly"
          :disabled="item.disabled"
          :editable="false"
          size="small"
          :clearable="item.clearable">
        </el-date-picker>

        <!-- time  时间 -->
        <div class="item-box" v-else-if="item.type ==='time'">
          <el-col :span="11">
            <el-form-item prop="date1">
              <el-date-picker
                placeholder="选择"
                style="width: 100%;"
                type="date"
                v-model="insideData[item.key]"
              ></el-date-picker>
            </el-form-item>
          </el-col>
          <el-col :span="2" class="line">-</el-col>
          <el-col :span="11">
            <el-form-item prop="date2">
              <el-time-picker placeholder="选择" style="width: 100%;" v-model="insideData[item.key]"></el-time-picker>
            </el-form-item>
          </el-col>
        </div>

        <!-- flage 开关 -->
        <el-switch v-else-if="item.type ==='flage'" v-model="insideData[item.key]"></el-switch>

        <!--  checkbox 多选 -->
        <el-checkbox-group v-else-if="item.type ==='checkbox'" v-model="insideData[item.key]">
          <el-checkbox
            :key="idx"
            :label="group.code"
            name="type"
            v-for="(group,idx) in item.group"
          >{{group.name}}</el-checkbox>
        </el-checkbox-group>

        <!-- radio 单选 -->
        <el-radio-group v-else-if="item.type ==='radio'" v-model="insideData[item.key]">
          <el-radio
            :disabled="item.disable?item.disable:false "
            :key="idx"
            :label="group.code"
            v-for="(group,idx) in item.group"
          >{{group.name}}</el-radio>
        </el-radio-group>

        <!-- textarea 文本域 -->
        <el-input
          :disabled="item.disabled?item.disabled:false"
          :maxlength="item.maxlength?item.maxlength:100"
          :resize="item.resize?item.resize:'none'"
          :rows="item.rows?item.rows:2"
          :show-word-limit="item.showWord?item.showWord:false"
          clearable
          placeholder="请输入"
          type="textarea"
          v-else-if="item.type ==='textarea' "
          v-model="insideData[item.key]"
        ></el-input>
        <!-- elTreeSelect -->
        <el-tree-select
          :data="item.group"
          :defaultExpandedKeys="item.expandedKeys ? item.expandedKeys : []"
          :props="item.defaultProps"
          @change="value=>change(value,item.change)"
          clearable
          ref="formTree"
          v-else-if="item.type ==='selectTree' "
          v-model="insideData[item.key]"
        ></el-tree-select>
        <!-- text -->
        <div v-if="item.type ==='text'" class="vc-form-text">{{ insideData[item.key] }}</div>
      </el-form-item>
    </template>
    </el-form>
  </div>
</template>
<style lang="less">
.xvc-dialog-form {
  .el-radio-group {
    float: left;
    margin-top: 10px;
  }
  .el-select {
    width: 100% !important;
  }
}
</style>
<script>
export default {
  name: 'Form',
  props: {
    formConfig: {
      type: Object,
      default () {
        return {
          items: [],
          params: {
            name: '',
            type: []
          }
        }
      }
    },
    defaultProps: {
      type: Object,
      default () {
        return {
          id: 'id',
          label: 'text',
          children: 'children',
          isLeaf: 'isLeaf'
        }
      }
    }
  },
  data () {
    /**
     * @phone
     * phone表单验证
     */
    return {
      name: 'name', // name
      selfData: {},
      insideData: {},
      insidFormConfigItems: [],
      phone: (rule, value, callback) => {
        const reg = /^1[3456789]\d{9}$/
        if (reg.test(value)) callback()
        callback(new Error('请输入正确的手机号'))
      }
    }
  },
  methods: {
    /**
     * change
     */
    change (value, fn, idx) {
      if (fn) {
        fn(value, idx)
      }
    },
    /*
      编码
    */
    half (rule, value, callback) {
      const reg = /[^\x00-\xff]/gi
      if (!reg.test(value)) callback()
      callback(new Error('只能输入半角字符'))
    },
    /*
      changeData
    */
    changeData () {
      this.insideData = JSON.parse(JSON.stringify(this.formConfig.params))
    },
    /*
      储存私有变量
    */
    getSelfData () {
      this.selfData = JSON.parse(JSON.stringify(this.formConfig.params))
      this.getInsideData()
    },

    /*
      配置insideData
    */
    getInsideData () {
      this.insideData = JSON.parse(JSON.stringify(this.formConfig.params)) // this.selfData
      this.name = this.formConfig.name
    },
    /**
     * 配置items
     */
    gitInsideItems () {
      this.insidFormConfigItems = [...this.formConfig.items]
      this.$forceUpdate()
    },
    /*
      重置
    */
    resetForm () {
      // 重置整个查询表单
      this.$nextTick(() => {
        this.$refs.Form && this.$refs.Form.resetFields()
        this.formConfig.params = JSON.parse(JSON.stringify(this.selfData))
        this.insideData = {}
        this.getInsideData()
        setTimeout(() => { this.clearValidate() }, 0)
      })
    },
    /**
     * 清除表单验证
     */
    clearValidate (prop) {
      this.$refs.Form && this.$refs.Form.clearValidate(prop || '')
    },
    /**
     * 保存
     */
    save (cb) {
      this.formConfig.params = JSON.parse(JSON.stringify(this.insideData))
      if (!cb) {
        let flage = true
        this.$refs.Form.validate(valid => {
          flage = valid
        })
        return flage
      }
      this.$refs.Form.validate(valid => {
        if (!valid) {
          return false
        }
        cb()
      })
    }
  },
  mounted () {
    this.getSelfData()
    this.gitInsideItems()
  },
  computed: {
    /**
     * 处理rules
     * @rules
     * 表单效验 通过 FormConfig.item[index].prop配置
     * 内置校验：@phone @email
     */
    rules: function (params) {
      let rules = {}
      this.formConfig.items.forEach(item => {
        this.$set(rules, item.key, [])
        if (item.rules) {
          if (item.rules.constructor === String) {
            this.$set(rules[item.key], 0, {
              validator: this[item.rules],
              trigger: 'blur'
            })
          }
          if (item.rules.constructor === Array) {
            item.rules.forEach(i => {
              rules[item.key].push({
                validator: this[i],
                trigger: 'blur'
              })
            })
          }
        }
        // 如果必填 分input 跟其他输入框样式 如 单选 下拉
        if (
          item.required &&
          (!item.type || item.type === 'input' || item.type === 'textarea')
        ) {
          rules[item.key].push({
            required: true,
            message: item.message,
            trigger: 'blur'
          })
        } else if (item.required) {
          rules[item.key].push({
            required: true,
            message: item.message,
            trigger: ['blur', 'change']
          })
        }

        // 如果是input要去掉收尾空格
        if (!item.type || item.type === 'input' || item.type === 'textarea') {
          rules[item.key].push({
            pattern: /^\S+(\s+\S+)*$/,
            message: '不能以空格开头或者结尾',
            trigger: 'blur'
          })
        }
        if (item.self) {
          if (item.self.constructor === Function) {
            rules[item.key].push({
              validator: item.self,
              trigger: 'blur'
            })
          }
          if (item.self.constructor === Array) {
            item.self.forEach(fn => {
              rules[item.key].push({
                validator: fn,
                trigger: 'blur'
              })
            })
          }
        }
      })
      return rules
    }
    /*
      this.form
    */
  },
  created () {},
  watch: {
    'formConfig.params': {
      handler (newName, oldName) {
        this.getInsideData()
      },
      immediate: true,
      deep: true
    },
    'formConfig.items': {
      handler (val) {
        this.gitInsideItems()
      },
      deep: true
    },
    insideData: {
      handler (val) {
        this.$emit('change', val)
      },
      deep: true
    }
  }
}
</script>
